/**
 * 三维向量类
 */
export class Vec3 {

  e0: number
  e1: number
  e2: number


  constructor(e0 = 0, e1 = 0, e2 = 0) {
    this.e0 = e0
    this.e1 = e1
    this.e2 = e2
  }

  // 向量加减乘除
  add(v: Vec3 | number) {
    return add(this, v)
  }

  sub(v: Vec3 | number) {
    return add(this, v, -1)
  }

  mul(num: number) {
    return mul(this, num)
  }

  div(num: number) {
    return mul(this, 1 / num)
  }

  //单位向量(向量方向)
  unitVec() {
    return this.div(this.length())
  }
  // 向量长度
  squaredLength() {
    return dot(this, this)
  }
  length() {
    return this.squaredLength() ** (1 / 2)
  }
}

/**
 * 向量加法
 * @param v1 
 * @param v2 
 * @returns 
 */
export function add(v1: Vec3, v2: number | Vec3, _sign: number = 1): Vec3 {
  const sign = Math.sign(_sign)
  return (
    typeof v2 === 'number'
      ? add(v1, new Vec3(v2, v2, v2))
      : new Vec3(v1.e0 + v2.e0 * sign, v1.e1 + v2.e1 * sign, v1.e2 + v2.e2 * sign)
  )
}

/**
 * 向量元素积
 * @param v1 
 * @param v2 
 * @returns 
 */
export function elemMul(v1: Vec3, v2: Vec3): Vec3 {
  return new Vec3(v1.e0 * v2.e0, v1.e1 * v2.e1, v1.e2 * v2.e2)
}

/**
 * 向量数乘
 * @param v1 
 * @param v2 
 * @returns 
 */
export function mul(v1: Vec3, num: number): Vec3 {
  return elemMul(v1, new Vec3(num, num, num))
}

/**
 * 向量点乘
 * @param v1 
 * @param v2 
 * @returns 
 */
export function dot(v1: Vec3, v2: Vec3) {
  return v1.e0 * v2.e0 + v1.e1 * v2.e1 + v1.e2 * v2.e2
}

/**
 * 向量叉乘
 * @param v1 
 * @param v2 
 * @returns 
 */
export function cross(v1: Vec3, v2: Vec3) {
  return new Vec3(
    (v1.e1 * v2.e2 - v1.e2 * v2.e1),
    (v1.e0 * v2.e2 - v1.e2 * v2.e0) * (-1),
    (v1.e0 * v2.e1 - v1.e1 * v2.e0)
  )
}

